﻿using WcfGeebaServer.DBDAL;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using Microsoft.VisualStudio.TestTools.UnitTesting.Web;
using WcfGeebaServer.Users;
using System.Collections.Generic;
using WcfGeebaServer.ContentManage;

namespace TestGeeba
{
    
    
    /// <summary>
    ///This is a test class for MemberDATest and is intended
    ///to contain all MemberDATest Unit Tests
    ///</summary>
    [TestClass()]
    public class MemberDATest
    {
        private MemberDA target;
        private GForum forum;
        private static int mid=0;

        public MemberDATest(){
            //Data.members.Clear(); // init members
            //Data.ClearDB();
            target = MemberDA.getMemberDA();
            forum = GForum.GetForum();
            
        }

        private TestContext testContextInstance;

        /// <summary>
        ///Gets or sets the test context which provides
        ///information about and functionality for the current test run.
        ///</summary>
        public TestContext TestContext
        {
            get
            {
                return testContextInstance;
            }
            set
            {
                testContextInstance = value;
            }
        }

        #region Additional test attributes
        // 
        //You can use the following additional attributes as you write your tests:
        //
        //Use ClassInitialize to run code before running the first test in the class
        //[ClassInitialize()]
        //public static void MyClassInitialize(TestContext testContext)
        //{
        //}
        //
        //Use ClassCleanup to run code after all tests in a class have run
        //[ClassCleanup()]
        //public static void MyClassCleanup()
        //{
        //}
        //
        //Use TestInitialize to run code before running each test
        //[TestInitialize()]
        //public void MyTestInitialize()
        //{
        //}
        //
        //Use TestCleanup to run code after each test has run
        //[TestCleanup()]
        //public void MyTestCleanup()
        //{
        //}
        //
        #endregion

        /// <summary>
        ///A test for AddMember
        ///</summary>
        // TODO: Ensure that the UrlToTest attribute specifies a URL to an ASP.NET page (for example,
        // http://.../Default.aspx). This is necessary for the unit test to be executed on the web server,
        // whether you are testing a page, web service, or a WCF service.
        [TestMethod()]
        public void AddMemberTest()
        {
            string username = "member" +(MemberDATest.mid++);
            string password = "1234";
            bool expected = true;
            bool actual;
            actual = target.AddMember(username, password);
            Assert.AreEqual(expected, actual);
        }

        /// <summary>
        ///A test for GetMember
        ///</summary>
        // TODO: Ensure that the UrlToTest attribute specifies a URL to an ASP.NET page (for example,
        // http://.../Default.aspx). This is necessary for the unit test to be executed on the web server,
        // whether you are testing a page, web service, or a WCF service.
        [TestMethod()]
        public void GetMemberTest()
        {
            Data.ClearDB();
            string username = "member" + (MemberDATest.mid++);
            Member expected = null;
            Member actual;
            actual = target.GetMember(username);
            Assert.IsNull(actual);

            expected = new Member(username, "1234", true);
            target.AddMember(username, "1234");
            actual = target.GetMember(username);
            Assert.AreEqual(expected, actual);
        }

        /// <summary>
        ///A test for GetMembers
        ///</summary>
        // TODO: Ensure that the UrlToTest attribute specifies a URL to an ASP.NET page (for example,
        // http://.../Default.aspx). This is necessary for the unit test to be executed on the web server,
        // whether you are testing a page, web service, or a WCF service.
        [TestMethod()]
        public void GetMembersTest()
        {
            Data.ClearDB();
            List<Member> expected = null;
            List<Member> actual;
            actual = target.GetMembers();
            Assert.IsNull(actual);

            string username = "member" + (MemberDATest.mid++);
            string pass = "1234";

            target.AddMember(username, pass);
            expected = new List<Member>();
            expected.Add(new Member(username, pass, true));
            actual = target.GetMembers();
            CollectionAssert.AreEqual(expected, actual);
        }

        /// <summary>
        ///A test for RemoveMember
        ///</summary>
        // TODO: Ensure that the UrlToTest attribute specifies a URL to an ASP.NET page (for example,
        // http://.../Default.aspx). This is necessary for the unit test to be executed on the web server,
        // whether you are testing a page, web service, or a WCF service.
        [TestMethod()]
        public void RemoveMemberTest()
        {
            string username = "member" + (MemberDATest.mid++);
            bool expected = false;
            bool actual;
            actual = target.RemoveMember(username);

            Assert.AreEqual(expected, actual);
        }

        /// <summary>
        ///A test for getMemberDA
        ///</summary>
        // TODO: Ensure that the UrlToTest attribute specifies a URL to an ASP.NET page (for example,
        // http://.../Default.aspx). This is necessary for the unit test to be executed on the web server,
        // whether you are testing a page, web service, or a WCF service.
        [TestMethod()]
        public void getMemberDATest()
        {
            MemberDA actual;
            actual = MemberDA.getMemberDA();
            Assert.IsNotNull(actual);
        }

        [TestMethod()]
        public void changeMemberPasswordTest()
        {
            //GForum forum = GForum.GetForum();
            string username = "member" + (MemberDATest.mid++);
            forum.register(username, "123");
            Assert.IsTrue(forum.login(forum.entry(), username, "123") != null);
            target.changeMemberPassword(target.GetMember(username), "321");
            Assert.IsTrue(forum.login(forum.entry(), username, "123") == null);
            Assert.IsTrue(forum.login(forum.entry(), username, "321") != null);
        }

        [TestMethod()]
        public void setInitialAdministratorTest()
        {
            string username = "member" + (MemberDATest.mid++);
            Member newAdmin = new Member(username, "123", true);
            target.AddMember(username, "123");
            target.setInitialAdministrator(newAdmin);
            Assert.IsTrue(Data.admin.Equals(newAdmin));
        }

        [TestMethod()]
        public void replaceAdministratorTest()
        {
            string username = "member" + (MemberDATest.mid++);
            Member oldAdmin = Data.admin;
            Member newAdmin = new Member(username, "123", true);
            target.AddMember(username, "123");
            target.replaceAdministrator(newAdmin);
            Assert.IsTrue(Data.admin.Equals(newAdmin));
        }

        [TestMethod()]
        public void getThreadCountTest()
        {
            string username = "member" + (MemberDATest.mid++);
            Member member = new Member(username,"123",true);
            forum.register(username, "123");
            forum.addSubForum("subforum", member);
            GSubForum sf = forum.getSubForum("subforum");
            sf.publish(new GThread("subj","content",member));
            sf.publish(new GThread("subj", "content", member));
            sf.publish(new GThread("subj", "content", member));
            Assert.IsTrue(target.getThreadCount(username) == 3);
        }

        [TestMethod()]
        public void isLawBreaker()
        {
            string username = "member" + (MemberDATest.mid++);
            Member member = new Member(username, "123", true);
            forum.register(username, "123");
            forum.addSubForum("subforum", member);
            GSubForum sf = forum.getSubForum("subforum");
            sf.publish(new GThread("subj", "content", member));
            Assert.IsFalse(target.isLawBreaker(username));
            member.setIsActive(false);
            sf.publish(new GThread("subj", "content", member));
            Assert.IsTrue(target.isLawBreaker(username));
        }

        [TestMethod()]
        public void setLawBreaker()
        {
            string username = "member" + (MemberDATest.mid++);
            Member member = new Member(username, "123", true);
            forum.register(username, "123");
            target.setLawBreaker(username, true);
            Assert.IsTrue(member.isLawBreaker());
            target.setLawBreaker(username, false);
            Assert.IsFalse(member.isLawBreaker());
        }

        [TestMethod()]
        public void setIsActive()
        {
            string username = "member" + (MemberDATest.mid++);
            Member member = new Member(username, "123", true);
            forum.register(username, "123");
            Assert.IsTrue(target.setIsActive(username, true));
            Assert.IsTrue(target.setIsActive(username, false));
            Assert.IsFalse(target.setIsActive("member" + (MemberDATest.mid++), true));
        }

        [TestMethod()]
        public void BanMember()
        {
            string username = "member" + (MemberDATest.mid++);
            Assert.IsFalse(target.BanMember(username));
            Member member = new Member(username, "123", true);
            forum.register(username, "123");
            Assert.IsTrue(target.BanMember(username));
        }

        [TestMethod()]
        public void IsBanned()
        {
            string username = "member" + (MemberDATest.mid++);
            Member member = new Member(username, "123", true);
            forum.register(username, "123");
            Assert.IsFalse(target.IsBanned(username));
            target.BanMember(username);
            Assert.IsTrue(target.IsBanned(username));
            
        }

        [TestMethod()]
        public void GetUserType()
        {
            User user = forum.entry();
            Assert.IsTrue(target.GetUserType(user.Username) == UserType.Guest);

            string username = "member" + (MemberDATest.mid++);
            forum.register(username, "123");
            Member mem = forum.login(user, username, "123");
            Assert.IsTrue(target.GetUserType(mem.Username) == UserType.Member);

            forum.addSubForum("subforum", mem);
            GSubForum sf = forum.getSubForum("subforum");
            SubForumDA.GetSubForumDA().AddModerator(sf, mem, new ModeratorInfo(DateTime.Now));
            Assert.IsTrue(target.GetUserType(mem.Username) == UserType.Moderator);

            target.replaceAdministrator(mem);
            Assert.IsTrue(target.GetUserType(mem.Username) == UserType.Admin);
            
            SubForumDA.GetSubForumDA().AddModerator(sf, mem, new ModeratorInfo(DateTime.Now));
            Assert.IsTrue(target.GetUserType(mem.Username) == UserType.Admin);

            SubForumDA.GetSubForumDA().RemoveModerator(sf, mem);
            Assert.IsTrue(target.GetUserType(mem.Username) == UserType.Admin);

            SubForumDA.GetSubForumDA().AddModerator(sf, mem, new ModeratorInfo(DateTime.Now));
            User user2 = forum.entry();
            string username2 = "member" + (MemberDATest.mid++);
            forum.register(username2, "123");
            Member mem2 = forum.login(user2, username2, "123");
            target.replaceAdministrator(mem2);

            Assert.IsTrue(target.GetUserType(mem.Username) == UserType.Moderator);
        }

    }
}
